/**
 * Copyright (c) 2009 Teoti Graphix, LLC See:
 *     http://tkarchitecture.teotigraphix.org
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author Michael Schmalle mschmalle@teotigraphix.com
 */
package test.suite.dxframework.patterns.component
{

import flash.events.Event;
import flash.events.IEventDispatcher;

import mx.events.FlexEvent;

import org.flexunit.Assert;
import org.flexunit.async.Async;
import org.fluint.uiImpersonation.UIImpersonator;
import org.teotigraphix.dx.core.ToolKitGlobals;
import org.teotigraphix.dx.core.dx_internal;
import org.teotigraphix.dx.event.BehaviorLayerEvent;
import org.teotigraphix.dx.event.ComponentLayerEvent;
import org.teotigraphix.dx.event.ModelLayerEvent;
import org.teotigraphix.dx.event.SkinEvent;
import org.teotigraphix.dx.event.ToolKitEvent;
import org.teotigraphix.dx.interfaces.IComponentBehavior;
import org.teotigraphix.dx.interfaces.IComponentModel;
import org.teotigraphix.dx.interfaces.IComponentSkin;
import org.teotigraphix.dx.interfaces.ICoreSkinAware;
import org.teotigraphix.dx.interfaces.IToolKitComponent;

import test.suite.dxframework.support.behavior.TestAlternateComponentBehaviorCore;
import test.suite.dxframework.support.behavior.TestBehavior;
import test.suite.dxframework.support.behavior.TestComponentBehaviorCore;
import test.suite.dxframework.support.component.TestComponent;
import test.suite.dxframework.support.component.TestModelComponent;
import test.suite.dxframework.support.component.factory.TestToolKitComponentFactory;
import test.suite.dxframework.support.layer.TestComponentBehaviorLayer;
import test.suite.dxframework.support.layer.TestComponentModelLayer;
import test.suite.dxframework.support.layer.TestComponentSkinLayer;
import test.suite.dxframework.support.model.TestComponentModelCore;
import test.suite.dxframework.support.model.TestModel;
import test.suite.dxframework.support.skin.BlankComponentSkin;
import test.suite.dxframework.support.skin.TestComponentSkin;


public class TC_DXComponent
{
	protected var component:TestComponent;
	private var scomponent:TestModelComponent;
	protected var behavior:TestBehavior;
	
	[Before(ui,async)]
	public function setUp():void
	{
		ToolKitGlobals.VALIDATION_EVENTS_ENABLED = true;
		
		component = new TestComponent();
		scomponent = new TestModelComponent();
		behavior = new TestBehavior();
		
		Async.proceedOnEvent(this, component, FlexEvent.CREATION_COMPLETE);
		UIImpersonator.addChild( component );
		UIImpersonator.addChild( scomponent );
	}
	
	[After]
	public function tearDown():void
	{
		UIImpersonator.removeChild( component );
		UIImpersonator.removeChild( scomponent );
		component = null;
		scomponent = null;
		behavior = null;
	}
	
	[Test]
	/**
	 * Tests the <code>behaviorLayer</code> assignment.
	 */
	public function test_set_behaviorLayer():void
	{
		Assert.assertNotNull( "component.behaviorLayer is null", component.behaviorLayer );
		Assert.assertTrue( "component.behaviorLayer not type TestComponentBehaviorLayer", 
			(component.behaviorLayer is TestComponentBehaviorLayer) );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>behaviors</code> assignment.
	 */
	public function test_set_behaviors():void
	{
		// should be null to begin with
		Assert.assertNull( "component.behaviors is not null", component.behaviors );
		
		var o:Object = {};
		// TODO you have to test the case where a dev tried to assign the array to
		// two components, I think this would be just a remove and add
		var behaviors:Array = [];
		o.behavior = new TestBehavior();
		behaviors.push( o.behavior );
		component.behaviors = behaviors;
		
		Assert.assertNotNull( "component.behaviors is null", component.behaviors );
		
		Async.handleEvent( this, component, 
			ToolKitEvent.VALIDATE_PROPERTIES_COMPLETE,
			component_set_behaviors_Handler, 500, o );

	}
	
	[Test(async)]
	/**
	 * Tests the <code>behaviors</code> unassignment.
	 */
	public function test_unset_behaviors():void
	{
		// should be null to begin with
		Assert.assertNull( "component.behaviors is not null", component.behaviors );
		
		var o:Object = {};
		
		var componentBehaviors:Array = [];
		o.componentBehavior = new TestBehavior();
		componentBehaviors.push( o.componentBehavior );
		component.behaviors = componentBehaviors;
		
		Assert.assertNotNull( "component.behaviors is null", component.behaviors );
		
		component.validateNow();
		
		o.componentPart = o.componentBehavior.mySkinPart as IEventDispatcher;
		
		// test to se that the handlers got added correctly
		_testComponentSet( o.componentBehavior, component, 
			TestComponentSkin( component.coreSkin ), o.componentPart );	
		
		// test that the behaviors unset unplugs the behavior correctly
		component.behaviors = null;
		
		Async.handleEvent( this, component, 
			ToolKitEvent.VALIDATE_PROPERTIES_COMPLETE,
			component_unset_behaviors_Handler, 500, o );
	}
	
	[Test]
	/**
	 * Tests the <code>coreSkin</code> assignment.
	 */
	public function test_set_coreSkin():void
	{
		Assert.assertNotNull( "component.coreSkin is null", component.coreSkin );
		Assert.assertTrue( "core not type TestComponentSkin", 
			(component.coreSkin is TestComponentSkin) );
	}
	
	[Test]
	/**
	 * Tests the <code>coreBehavior</code> assignment.
	 */
	public function test_set_coreBehavior():void
	{
		Assert.assertNotNull( "component.coreBehavior is null", component.coreBehavior );
		Assert.assertTrue( "core not type TestComponentBehaviorCore", 
			(component.coreBehavior is TestComponentBehaviorCore) );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>coreBehavior</code> assignment.
	 */
	public function test_set_coreBehavior_AfterAddChild():void
	{
		// FIXME
		return;
		
/*
commitProperties()

-> ToolKitManager.validatePreCommitProperties(this);

    -> ToolKitHelper.setCoreBehavior(client, new, old)
        -> client.component = null
        1) removes the component ref [TestComponent] from [TestComponentCore]
        2) removes the skin ref [TestComponentSkin] from [TestComponentCore]
        -> client.component = TestComponent
        3) adds the component ref [TestComponent] to [TestAlternateComponentCoreBehavior] 
        [redundent (this should not have to be added back)]
        4) adds the skin ref [TestComponentSkin] to [TestAlternateComponentCoreBehavior]

super.commitProperties() -> validateSkinChange()

    -> detachSkin()
    5) removes the skin [TestComponentSkin] ref from [TestAlternateComponentCoreBehavior]
    -> attachSkin()
    6) adds the skin ref [BlankSkin] to [TestAlternateComponentCoreBehavior]

-> ToolKitManager.validateCommitProperties(this);

    -> core.validateProperties()
    7) updates style bindings on skin

*/
		var o:Object = {};
		Assert.assertNotNull( "component.coreBehavior is null", component.coreBehavior );
		
		o.oldCoreBehavior = component.coreBehavior;
		
		// this is so we can test the removal of the propertyChange on the skin
		o.oldSkin = component.coreSkin;
		component.setStyle( "skinClass", BlankComponentSkin );
				
		o.coreBehavior = new TestAlternateComponentBehaviorCore();
		component.coreBehavior = o.coreBehavior;
		
		Async.handleEvent( this, component, 
			ToolKitEvent.VALIDATE_PROPERTIES_COMPLETE,
			component_set_coreBehavior_AfterAddChildHandler, 500, o );		
	}
	
	[Test]
	/**
	 * Tests the <code>coreModel</code> assignment.
	 */
	public function test_set_coreModel():void
	{
		Assert.assertNotNull( "component.coreModel is null", component.coreModel );
		Assert.assertTrue( "core not type TestComponentModelCore", 
			(component.coreModel is TestComponentModelCore) );		
	}
	
	[Test]
	/**
	 * Tests the <code>modelLayer</code>.
	 */
	public function test_set_modelLayer():void
	{
		Assert.assertNotNull( "scomponent.modelLayer is null", scomponent.modelLayer );
		Assert.assertTrue( "scomponent.modelLayer not type TestComponentModelLayer", 
			(scomponent.modelLayer is TestComponentModelLayer) );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>models</code> assignment.
	 */
	public function test_set_models():void
	{
		// should be null to begin with
		Assert.assertNull( "scomponent.models is not null", scomponent.models );
		
		var o:Object = {};
		// TODO you have to test the case where a dev tried to assign the array to
		// two components, I think this would be just a remove and add
		var models:Array = [];
		o.model = new TestModel();
		models.push( o.model );
		scomponent.models = models;
		
		Assert.assertNotNull( "scomponent.services is null", scomponent.models );
		
		Async.handleEvent( this, scomponent, 
			ToolKitEvent.VALIDATE_PROPERTIES_COMPLETE,
			scomponent_set_models_Handler, 500, o );
	}
	
	[Test]
	/**
	 * Tests the <code>skinLayer</code>.
	 */
	public function test_set_skinLayer():void
	{
		Assert.assertNotNull( "component.skinLayer is null", component.skinLayer );
		Assert.assertTrue( "component.skinLayer not type TestComponentSkinLayer", 
			(component.skinLayer is TestComponentSkinLayer) );
	}
	
	[Test]
	/**
	 * Tests the <code>toolKitFactory</code> assignment.
	 */
	public function test_set_toolKitFactory():void
	{
		// set in activateToolKit() override
		Assert.assertNotNull( "component.toolKitFactory is null", component.toolKitFactory );
		Assert.assertTrue( "component.toolKitFactory not type TestToolKitComponentFactory", 
			(component.toolKitFactory is TestToolKitComponentFactory) );
	}
	
	[Test]
	/**
	 * Tests the <code>toolKitInitialized</code> assignment.
	 */
	public function test_set_toolKitInitialized():void
	{
		// initialize() -> childrenCreated() -> TKM::validateChildren() -> true
		// children are created before this is true
		Assert.assertTrue( "component not initialized", component.toolKitInitialized );
	}
	
	//----------------------------------
	//  Public :: Methods
	//----------------------------------
	
	[Test]
	/**
	 * Tests the <code>initializeToolKit()</code> method call.
	 */
	public function test_call_initializeToolKit():void
	{
		// called from addChild() -> parentChanged() -> ToolKitManager.start()
		// BEFORE the default toolkit components are initialized from the
		// factory or existing instances
		Assert.assertTrue( "initializeToolKitFlag false", component.initializeToolKitFlag );
	}
	
	[Test]
	/**
	 * Tests the <code>invalidateSkin()</code> method call.
	 */
	public function test_call_invalidateSkin():void
	{
		component.invalidateSkin();
		Assert.assertTrue( "invalidateSkinFlag false", component.invalidateSkinFlag );
	}
	
	[Test]
	/**
	 * Tests the <code>activate()</code> method call.
	 */
	public function test_call_activate():void
	{
		// ToolKitComponent() -> ToolKitManager.activate() -> 
		Assert.assertTrue( "activateFlag false", component.activateFlag );
	}
	
	[Test]
	/**
	 * Tests the <code>startToolKit()</code> method call.
	 */
	public function test_call_startToolKit():void
	{
		// addChild() -> childAdded() -> initialize() -> childrenCreated()
		// -> ToolKitManager.validateChildrenCreated()
		// 'toolKitInitialized' is called right after this method returns
		// dispatched before :: ToolKitEvent.TOOL_KIT_START
		// disaptched after  :: ToolKitEvent.TOOL_KIT_START_COMPLETE
		Assert.assertTrue( "startToolKitFlag false", component.startToolKitFlag );
	}
	
	[Test]
	/**
	 * Tests the <code>stopToolKit()</code> method call.
	 */
	public function test_call_stopToolKit():void
	{
		// removeChild() -> childRemoved() -> parentChanged() -> ToolKitManager.stop()
		// dispatched before :: ToolKitEvent.TOOL_KIT_STOP
		// disaptched after  :: ToolKitEvent.TOOL_KIT_STOP_COMPLETE		
		UIImpersonator.removeChild(component);
		Assert.assertTrue( "stopToolKitFlag false", component.stopToolKitFlag );
		UIImpersonator.addChild(component);
	}	
	
	[Test]
	/**
	 * Tests the <code>stylesInitialized()</code> method call.
	 */
	public function test_call_stylesInitialized():void
	{
		// addChild() -> addingChild()
		Assert.assertTrue( "stylesInitializedFlag false", component.stylesInitializedFlag );
	}
	
	//----------------------------------
	//  Protected :: Methods
	//----------------------------------
	
	[Test]
	/**
	 * Tests the <code>behaviorAdded()</code> method call when a behavior 
	 * is added.
	 */
	public function test_call_behaviorAdded():void
	{
		var api:Class = TestBehavior;
		var behavior:TestBehavior = new TestBehavior();
		
		component.behaviorLayer.registerBehavior( api, behavior );
		
		Assert.assertEquals( "behaviorAdded(api) not called correctly", 
			component.behaviorAddedObject.api, api );
		Assert.assertEquals( "behaviorAdded(behavior) not called correctly", 
			component.behaviorAddedObject.behavior, behavior );
	}	
	
	[Test]
	/**
	 * Tests the <code>behaviorRemoved()</code> method call when a behavior 
	 * is removed.
	 */
	public function test_call_behaviorRemoved():void
	{
		var api:Class = TestBehavior;
		var behavior:TestBehavior = new TestBehavior();
		
		component.behaviorLayer.registerBehavior( api, behavior );
		component.validateNow();
		component.behaviorLayer.removeBehavior( api );
		
		Assert.assertEquals( "behaviorRemoved(api) not called correctly", 
			component.behaviorRemovedObject.api, api );
		Assert.assertEquals( "behaviorRemoved(behavior) not called correctly", 
			component.behaviorRemovedObject.behavior, behavior );
	}
	
	[Test]
	/**
	 * Tests the <code>modelAdded()</code> method call when a service 
	 * is added.
	 */
	public function test_call_modelAdded():void
	{
		var api:Class = TestModel;
		var model:TestModel = new TestModel();
		
		scomponent.modelLayer.registerModel( api, model );
		
		Assert.assertEquals( "modelAdded(api) not called correctly", 
			scomponent.modelAddedObject.api, api );
		Assert.assertEquals( "modelAdded(service) not called correctly", 
			scomponent.modelAddedObject.model, model );
	}
	
	[Test]
	/**
	 * Tests the <code>modelRemoved()</code> method call when a service 
	 * is removed.
	 */
	public function test_call_modelRemoved():void
	{
		var api:Class = TestModel;
		var model:TestModel = new TestModel();
		
		scomponent.modelLayer.registerModel( api, model );
		scomponent.validateNow();
		scomponent.modelLayer.removeModel( api );
		
		Assert.assertEquals( "modelRemoved(api) not called correctly", 
			scomponent.modelRemovedObject.api, api );
		Assert.assertEquals( "modelRemoved(service) not called correctly", 
			scomponent.modelRemovedObject.model, model );
	}	
	
	//----------------------------------
	//  Public :: Events
	//----------------------------------
	
	// behaviorAdd, behaviorRemove, layerActivate, layerDeactivate, 
	// serviceAdd, serviceRemove, skinAdd, skinRemove
	
	[Test(async)]
	/**
	 * Tests the <code>behaviorAdd</code> event when a behavior 
	 * is added.
	 */
	public function test_dispatch_behaviorAdd():void
	{
		var o:Object = {};
		o.api = TestBehavior;
		o.behavior = new TestBehavior();
		
		Async.handleEvent( this, component, 
			BehaviorLayerEvent.BEHAVIOR_ADD,
			component_behaviorAdd_Handler, 500, o );		
		
		component.behaviorLayer.registerBehavior( o.api, o.behavior );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>behaviorRemove</code> event when a behavior 
	 * is removed.
	 */
	public function test_dispatch_behaviorRemove():void
	{
		var o:Object = {};
		o.api = TestBehavior;
		o.behavior = new TestBehavior();
		
		Async.handleEvent( this, component, 
			BehaviorLayerEvent.BEHAVIOR_ADD,
			component_behaviorAdd_Handler, 500, o );
		
		Async.handleEvent( this, component, 
			BehaviorLayerEvent.BEHAVIOR_REMOVE,
			component_behaviorRemove_Handler, 500, o );
		
		component.behaviorLayer.registerBehavior( o.api, o.behavior );
		component.behaviorLayer.removeBehavior( o.api );
	}

	[Test(async)]
	/**
	 * Tests the <code>layerActivate</code> event when a behavior 
	 * is removed.
	 */
	public function test_dispatch_layerActivate():void
	{
		var o:Object = {};
		o.layer = new TestComponentBehaviorLayer();
		
		Async.handleEvent( this, component, 
			ComponentLayerEvent.LAYER_ACTIVATE,
			component_layerActivate_Handler, 500, o );	
		
		component.behaviorLayer = o.layer;
	}
	
	[Test(async)]
	/**
	 * Tests the <code>layerDeactivate</code> event when a behavior 
	 * is removed.
	 */
	public function test_dispatch_layerDeactivate():void
	{
		var o:Object = {};
		o.oldLayer = component.behaviorLayer;
		o.layer = new TestComponentBehaviorLayer();
		
		Async.handleEvent( this, component, 
			ComponentLayerEvent.LAYER_DEACTIVATE,
			component_layerDeactivate_Handler, 500, o );
		
		component.behaviorLayer = o.layer;
	}	
	
	[Test(async)]
	/**
	 * Tests the <code>modelAdd</code> event when a service 
	 * is added.
	 */
	public function test_dispatch_modelAdd():void
	{
		var o:Object = {};
		o.api = TestModel;
		o.model = new TestModel();
		
		Async.handleEvent( this, scomponent, 
			ModelLayerEvent.MODEL_ADD,
			component_modelAdd_Handler, 500, o );
		
		scomponent.modelLayer.registerModel( o.api, o.model );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>modelRemove</code> event when a service 
	 * is removed.
	 */
	public function test_dispatch_modelRemove():void
	{
		var o:Object = {};
		o.api = TestModel;
		o.model = new TestModel();
		
		Async.handleEvent( this, scomponent, 
			ModelLayerEvent.MODEL_ADD,
			component_modelAdd_Handler, 500, o );
		Async.handleEvent( this, scomponent, 
			ModelLayerEvent.MODEL_REMOVE,
			component_modelRemove_Handler, 500, o );					
		
		scomponent.modelLayer.registerModel( o.api, o.model );
		scomponent.modelLayer.removeModel( o.api );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>skinAdd</code> event when a skin 
	 * is added.
	 */
	public function test_dispatch_skinAdd():void
	{
		// FIXME
		return;
				
		var o:Object = {};
		o.skinClass = BlankComponentSkin;
		
		Async.handleEvent( this, component, 
			SkinEvent.SKIN_ADD,
			component_skinAdd_Handler, 500, o );		
		
		component.setStyle( "skinClass", o.skinClass );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>skinRemove</code> event when a skin 
	 * is removed.
	 */
	public function test_dispatch_skinRemove():void
	{
		// FIXME
		return;
		
		var o:Object = {};
		o.skinClass = TestComponentSkin;
		
		Async.handleEvent( this, component, 
			SkinEvent.SKIN_REMOVE,
			component_skinRemove_Handler, 500, o );		
		
		component.setStyle( "skinClass", BlankComponentSkin );
		component.validateNow();
		component.setStyle( "skinClass", o.skinClass );
	}
	
	
	
	
	
	
	
	
	
	//--------------------------------------------------------------------------
	//
	//  Protected :: Handlers
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @private
	 */
	protected function component_set_behaviors_Handler( event:Event, data:Object ):void 
	{
		// test that the behavior got added to the behaviorLocator
		var test:IComponentBehavior = component.behaviorLayer.getBehavior( TestBehavior );
		Assert.assertStrictlyEquals( "IComponentBehavior not added to component.behaviorLayer", 
			data.behavior, test );
	}
	
	/**
	 * @private
	 */
	protected function component_unset_behaviors_Handler( event:Event, data:Object ):void 
	{
		_testComponentUnset( data.componentBehavior, component, 
			TestComponentSkin( component.coreSkin ), data.componentPart );
	}
	
	/**
	 * @private
	 */
	protected function component_set_coreBehavior_AfterAddChildHandler( event:Event, data:Object ):void 
	{
		Assert.assertStrictlyEquals( "", data.coreBehavior, component.coreBehavior );
		
		Assert.assertTrue( "", (component.coreBehavior is TestAlternateComponentBehaviorCore) );
		
		// test that component is null
		Assert.assertNull( "old coreBehavior.component not null", 
			data.oldCoreBehavior.component );
		Assert.assertNull( "old coreBehavior.uiComponent not null", 
			data.oldCoreBehavior.uicomponent );
//		Assert.assertNull( "old coreBehavior.testComponent not null", 
//			data.oldCoreBehavior.testComponent );
//		Assert.assertNull( "old coreBehavior.mySkinPart not null", 
//			data.oldCoreBehavior.mySkinPart );
		
		Assert.assertNull( "old coreBehavior.skin not null", 
			data.oldCoreBehavior.dx_internal::getSkin() );
		
		// test that the component_handler "myPropertyChanged" got removed
		Assert.assertFalse( "old coreBehavior did not remove 'myPropertyChanged' component_handler", 
			component.hasEventListener("myPropertyChanged") );
		
		// The flex binding system probably has propertyChange on this instance
		// I don't think I can really test this here
//		assertFalse( "old coreBehavior did not remove 'propertyChange' from skin", 
//			data.oldSkin.hasEventListener("propertyChange") );
	}
	
	/**
	 * @private
	 */
	protected function scomponent_set_models_Handler( event:Event, data:Object ):void 
	{
		// test that the behavior got added to the behaviorLocator
		var test:IComponentModel = scomponent.modelLayer.getModel( TestModel );
		Assert.assertStrictlyEquals( "IComponentModel not added to scomponent.modelLayer", 
			data.model, test );
	}
	
	/**
	 * @private
	 */
	protected function component_behaviorAdd_Handler( event:BehaviorLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, BehaviorLayerEvent.BEHAVIOR_ADD );
		Assert.assertStrictlyEquals( "event.api", event.api, data.api );
		Assert.assertStrictlyEquals( "event.behavior", event.behavior, data.behavior );
		Assert.assertStrictlyEquals( "event.component", event.component, component );
	}
	
	/**
	 * @private
	 */
	protected function component_behaviorRemove_Handler( event:BehaviorLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, BehaviorLayerEvent.BEHAVIOR_REMOVE );
		Assert.assertStrictlyEquals( "event.api", event.api, data.api );
		Assert.assertStrictlyEquals( "event.behavior", event.behavior, data.behavior );
		Assert.assertStrictlyEquals( "event.component", event.component, component );
	}
	
	/**
	 * @private
	 */
	protected function component_layerActivate_Handler( event:ComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, ComponentLayerEvent.LAYER_ACTIVATE );
		Assert.assertStrictlyEquals( "event.layer", event.layer, data.layer );
		Assert.assertStrictlyEquals( "event.component", event.component, component );
	}
	
	/**
	 * @private
	 */
	protected function component_layerDeactivate_Handler( event:ComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, ComponentLayerEvent.LAYER_DEACTIVATE );
		Assert.assertStrictlyEquals( "event.layer", event.layer, data.oldLayer );
		Assert.assertStrictlyEquals( "event.component", event.component, component );
	}
	
	/**
	 * @private
	 */
	protected function component_modelAdd_Handler( event:ModelLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, ModelLayerEvent.MODEL_ADD );
		Assert.assertStrictlyEquals( "event.api api", event.api, data.api );
		Assert.assertStrictlyEquals( "event.model", event.model, data.model );
		Assert.assertStrictlyEquals( "event.component", event.component, scomponent );
	}
	
	/**
	 * @private
	 */
	protected function component_modelRemove_Handler( event:ModelLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, ModelLayerEvent.MODEL_REMOVE );
		Assert.assertStrictlyEquals( "event.api", event.api, data.api );
		Assert.assertStrictlyEquals( "event.model", event.model, data.model );
		Assert.assertStrictlyEquals( "event.component", event.component, scomponent );
	}
	
	
	/**
	 * @private
	 */
	protected function component_skinAdd_Handler( event:SkinEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, SkinEvent.SKIN_ADD );
		Assert.assertTrue( "event.skin incorrect", (event.skin is data.skinClass ));
	}
	
	/**
	 * @private
	 */
	protected function component_skinRemove_Handler( event:SkinEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, SkinEvent.SKIN_REMOVE );
		Assert.assertTrue( "event.skin incorrect", (event.skin is data.skinClass ));
	}
	
	
	
	
	
	
	
	
	/**
	 * @private
	 * Copied from BehaviorProperties_TC.as
	 */
	protected function _testComponentSet(
		behavior:TestBehavior, component:IToolKitComponent, 
		skin:IComponentSkin, part:IEventDispatcher ):void
	{
		Assert.assertNotNull( "behavior is null", behavior);
		Assert.assertNotNull( "component is null", component);
		Assert.assertNotNull( "skin is null", skin);
		Assert.assertNotNull( "part is null", part);
				
		// test the ref to the component was set
		Assert.assertStrictlyEquals( component, behavior.component );
		
		// test [ComponentAlias] was set
		Assert.assertNotNull( "behavior.myComponentAlias is null", behavior.myComponentAlias );
		// test [Part] was set
		Assert.assertNotNull( "behavior.mySkinPart is null", behavior.mySkinPart );
		
		// test that the component has component, skin and part handlers
		Assert.assertTrue( "component does not have 'myComponentPropertyChanged' component_handler", 
			component.hasEventListener("myComponentPropertyChanged") );
		Assert.assertTrue( "component.skin does not have 'mySkinPropertyChanged' skin_handler", 
			ICoreSkinAware(component).coreSkin.hasEventListener("mySkinPropertyChanged") );		
		Assert.assertTrue( "component.skin.part does not have 'mySkinPartPropertyChanged' part_handler", 
			part.hasEventListener("mySkinPartPropertyChanged") );
		
		// dispatch the individual events through the component, skin and skin part
		component.dispatchEvent(new Event("myComponentPropertyChanged"));
		skin.dispatchEvent(new Event("mySkinPropertyChanged"));
		part.dispatchEvent(new Event("mySkinPartPropertyChanged"));
		
		// test the flags to see if the handlers on the behavior were fired
		Assert.assertTrue( "component_handler did not fire", behavior.componentFlag );
		Assert.assertTrue( "skin_handler did not fire", behavior.skinFlag );
		Assert.assertTrue( "skinpart_handler did not fire", behavior.skinPartFlag );
	}

	/**
	 * @private
	 * Copied from BehaviorProperties_TC.as
	 */
	protected function _testComponentUnset(
		behavior:TestBehavior, component:IToolKitComponent, 
		skin:IComponentSkin, part:IEventDispatcher ):void
	{
		Assert.assertNotNull( "behavior is null", behavior);
		Assert.assertNotNull( "component is null", component);
		Assert.assertNotNull( "skin is null", skin);
		Assert.assertNotNull( "part is null", part);
		
		Assert.assertNull( "behavior.component not null", behavior.component );
		
		// test [ComponentAlias] was unset
		Assert.assertNull( "behavior.myComponentAlias is not null", behavior.myComponentAlias );
		// test [Part] was unset
		Assert.assertNull( "behavior.mySkinPart is not null", behavior.mySkinPart );
		
		// test that the component has removed, skin and part handlers
		Assert.assertFalse( "component does not have 'myComponentPropertyChanged' component_handler", 
			component.hasEventListener("myComponentPropertyChanged") );
		Assert.assertFalse( "component.skin does not have 'mySkinPropertyChanged' skin_handler", 
			ICoreSkinAware(component).coreSkin.hasEventListener("mySkinPropertyChanged") );		
		Assert.assertFalse( "component.skin.part does not have 'mySkinPartPropertyChanged' part_handler", 
			part.hasEventListener("mySkinPartPropertyChanged") );		
		
		// dispatch the individual events through the component, 
		// we do it a seconf time here to see if the flags switch back to
		// false, if they do, the handlers did not get removed
		component.dispatchEvent(new Event("myComponentPropertyChanged"));
		skin.dispatchEvent(new Event("mySkinPropertyChanged"));
		part.dispatchEvent(new Event("mySkinPartPropertyChanged"));
		
		// test the flags to see if the handlers on the behavior were not fired
		Assert.assertTrue( "component_handler did fire", behavior.componentFlag );
		Assert.assertTrue( "skin_handler did fire", behavior.skinFlag );
		Assert.assertTrue( "skinpart_handler did fire", behavior.skinPartFlag );
	}
}
}